/* test9-4.c */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <netinet/ip.h>  // 添加这一行以定义 struct ip
#include <netinet/tcp.h> // 添加这一行以定义 struct tcphdr
#include <arpa/inet.h>
#include <net/if.h>

int openRawSocket(void) {
    int sock;
    if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0) {
        perror("raw socket create error\n");
        exit(1);
    }
    return sock;
}

int setPromisc(char *interface, int sock) {
    struct ifreq ifr;
    strncpy(ifr.ifr_name, interface, sizeof(interface));
    if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
        perror("set promisc error one\n");
        exit(1);
    }
    ifr.ifr_flags |= IFF_PROMISC;
    if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) {
        perror("Can not set PRoMisc flag\n");
        exit(1);
    }
    return 0;
}

int main() {
    int sock;
    sock = openRawSocket();
    printf("raw socket is %d\n", sock);
    char buffer[65535];
    int bytesRecieved;
    struct sockaddr_in from;
    struct ip *iph;
    struct tcphdr *tcph;
    socklen_t fromlen;

    setPromisc("ens33", sock); // 修改为实际的网络接口名称

    printf("ip header is %ld\n", sizeof(struct ip));
    printf("tcp header is %ld\n", sizeof(struct tcphdr));

    while (1) {
        fromlen = sizeof(from);
        bytesRecieved = recvfrom(sock, buffer, sizeof(buffer), 0, (struct sockaddr *)&from, &fromlen);
        printf("\nBytes received: %d\n", bytesRecieved);
        printf("source address: %s\n", inet_ntoa(from.sin_addr));

        iph = (struct ip *)buffer;
        if (iph->ip_p == 6) { // 如果为TCP协议
            printf("Dest address is: %s\n", inet_ntoa(iph->ip_dst));
            printf("ip header Length is %d\n", iph->ip_hl);
            printf("Protocol: %d\n", iph->ip_p);
            printf("Type of Service: %d\n", iph->ip_tos);
            printf("Time to live is %d\n", iph->ip_ttl);
            printf("Checksum is: %d\n", iph->ip_sum);

            tcph = (struct tcphdr *)(buffer + 20); // IP数据包和TCP数据包有20个字节的偏移
            printf("Dest Port is: %d\n", ntohs(tcph->th_dport));
            printf("Source port is: %d\n", ntohs(tcph->th_sport));
            printf("Seg Number: %d\n", ntohl(tcph->th_seq));
            printf("Ack Number: %d\n", ntohl(tcph->th_ack));
            printf("Flags: %d\n", tcph->th_flags);
        }
    }

    return 0;
}